<script setup>
import { ref, reactive, onMounted, nextTick } from 'vue';
import { marked } from 'marked'; // 如果没有安装，请使用 npm install marked
import request from '../utils/request.js';

// 聊天状态和消息历史
const chatMessages = ref([]);
const userInput = ref('');
const isLoading = ref(false);
const chatContainerRef = ref(null);
const availableModels = ref([]);
const selectedModel = ref('deepseek-ai/DeepSeek-V3');

// 配置选项
const chatConfig = reactive({
  temperature: 0.7,
  max_tokens: 1024,
  system_message: "You are a helpful assistant."
});

// 获取可用模型
onMounted(async () => {
  try {
    const models = await request.get('/ai_chat/models');
    availableModels.value = models;
  } catch (error) {
    console.error('获取模型列表失败:', error);
  }
});

// 发送消息
const sendMessage = async () => {
  const message = userInput.value.trim();
  if (!message) return;

  // 添加用户消息到对话
  chatMessages.value.push({
    role: 'user',
    content: message
  });

  // 清空输入框
  userInput.value = '';

  // 滚动到底部
  await scrollToBottom();

  // 设置加载状态
  isLoading.value = true;

  try {
    // 准备AI响应的占位符
    const aiMessageIndex = chatMessages.value.length;
    chatMessages.value.push({
      role: 'assistant',
      content: '',
      loading: true
    });

    // 准备请求消息，不包括最新添加的AI响应
    const messages = chatMessages.value
        .slice(0, -1)
        .map(msg => ({
          role: msg.role,
          content: msg.content
        }));

    // 确保第一条消息是系统消息
    if (!messages.length || messages[0].role !== 'system') {
      messages.unshift({
        role: 'system',
        content: chatConfig.system_message
      });
    }

    // 使用fetch API发送POST请求接收流式响应
    fetch(`${request.defaults.baseURL || ''}/ai_chat/chat`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        // 添加可能的授权信息
        ...(localStorage.getItem('token') ? { 'Authorization': `Bearer ${localStorage.getItem('token')}` } : {})
      },
      body: JSON.stringify({
        messages,
        model: selectedModel.value,
        temperature: chatConfig.temperature,
        max_tokens: chatConfig.max_tokens
      })
    })
        .then(response => {
          if (!response.ok) {
            throw new Error(`HTTP error! Status: ${response.status}`);
          }

          const reader = response.body.getReader();
          const decoder = new TextDecoder('utf-8');

          // 处理流式响应
          function processStream() {
            return reader.read().then(({ done, value }) => {
              // 如果流结束，结束处理
              if (done) {
                chatMessages.value[aiMessageIndex].loading = false;
                isLoading.value = false;
                return;
              }

              // 解码二进制数据
              const chunk = decoder.decode(value, { stream: true });

              // 处理SSE格式的数据
              const lines = chunk.split('\n\n');
              for (const line of lines) {
                if (line.startsWith('data: ')) {
                  try {
                    const data = JSON.parse(line.substring(6));

                    // 如果收到结束信号
                    if (data.done) {
                      chatMessages.value[aiMessageIndex].loading = false;
                      isLoading.value = false;
                      return;
                    }

                    // 追加内容
                    if (data.content) {
                      chatMessages.value[aiMessageIndex].content += data.content;
                      scrollToBottom();
                    }
                  } catch (e) {
                    console.error('解析响应数据出错:', e, line);
                  }
                }
              }

              // 继续处理流
              return processStream();
            });
          }

          return processStream();
        })
        .catch(error => {
          console.error('流式响应错误:', error);
          chatMessages.value[aiMessageIndex].content += '\n\n[连接中断: ' + error.message + ']';
          chatMessages.value[aiMessageIndex].loading = false;
          isLoading.value = false;
        });

  } catch (error) {
    console.error('发送消息失败:', error);
    isLoading.value = false;
    chatMessages.value.push({
      role: 'system',
      content: `发送消息失败: ${error.message || '未知错误'}`,
      isError: true
    });
  }
};

// 以下是使用axios的替代方法，如果fetch API不合适可以使用这个
// 注意：该方法不启用，仅作参考
const sendMessageWithAxios = async () => {
  const message = userInput.value.trim();
  if (!message) return;

  // 添加用户消息到对话
  chatMessages.value.push({
    role: 'user',
    content: message
  });

  // 清空输入框
  userInput.value = '';

  // 滚动到底部
  await scrollToBottom();

  // 设置加载状态
  isLoading.value = true;

  try {
    // 准备AI响应的占位符
    const aiMessageIndex = chatMessages.value.length;
    chatMessages.value.push({
      role: 'assistant',
      content: '',
      loading: true
    });

    // 准备请求消息
    const messages = chatMessages.value
        .slice(0, -1)
        .map(msg => ({
          role: msg.role,
          content: msg.content
        }));

    // 确保第一条消息是系统消息
    if (!messages.length || messages[0].role !== 'system') {
      messages.unshift({
        role: 'system',
        content: chatConfig.system_message
      });
    }

    // 使用axios发送请求并处理流式响应
    const response = await request({
      url: '/ai_chat/chat',
      method: 'POST',
      data: {
        messages,
        model: selectedModel.value,
        temperature: chatConfig.temperature,
        max_tokens: chatConfig.max_tokens
      },
      responseType: 'stream'
    });

    // 处理流式响应
    const reader = response.body.getReader();
    const decoder = new TextDecoder();

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      const chunk = decoder.decode(value, { stream: true });
      const lines = chunk.split('\n\n');

      for (const line of lines) {
        if (line.startsWith('data: ')) {
          const data = JSON.parse(line.substring(6));

          if (data.done) {
            chatMessages.value[aiMessageIndex].loading = false;
            isLoading.value = false;
            break;
          }

          if (data.content) {
            chatMessages.value[aiMessageIndex].content += data.content;
            scrollToBottom();
          }
        }
      }
    }

  } catch (error) {
    console.error('发送消息失败:', error);
    isLoading.value = false;
    chatMessages.value.push({
      role: 'system',
      content: `发送消息失败: ${error.message || '未知错误'}`,
      isError: true
    });
  }
};

// 滚动聊天容器到底部
const scrollToBottom = async () => {
  await nextTick();
  if (chatContainerRef.value) {
    chatContainerRef.value.scrollTop = chatContainerRef.value.scrollHeight;
  }
};

// 清空聊天历史
const clearChat = () => {
  chatMessages.value = [];
};

// 按下回车键发送消息
const handleKeyDown = (event) => {
  if (event.key === 'Enter' && !event.shiftKey) {
    event.preventDefault();
    sendMessage();
  }
};

// 格式化Markdown内容为HTML
const formatMarkdown = (content) => {
  if (!content) return '';
  try {
    // 配置marked选项，启用自动链接等
    marked.setOptions({
      breaks: true,       // 将换行符转换为<br>
      gfm: true,          // 使用GitHub风格的Markdown
      headerIds: false,   // 禁用header IDs
      mangle: false,      // 禁用转义
      sanitize: false,    // 允许HTML标签
    });

    // 替换可能导致额外间距的标签
    let html = marked(content);

    // 压缩连续的空行
    html = html.replace(/<p><br><\/p>/g, '<br>');
    html = html.replace(/<p>\s*<\/p>/g, '');

    // 移除段落标签，保留内容
    html = html.replace(/<p>(.*?)<\/p>/g, '$1<br>');
    html = html.replace(/<br>$/, ''); // 移除末尾的<br>

    return html;
  } catch (e) {
    console.error('Markdown解析错误:', e);
    return content;
  }
};
</script>

<template>
  <div class="chat-container">
    <div class="chat-header">
      <h2>AI 助手</h2>
      <div class="chat-actions">
        <select v-model="selectedModel" class="model-selector">
          <option v-for="model in availableModels" :key="model.id" :value="model.id">
            {{ model.name }}
          </option>
        </select>
        <button @click="clearChat" class="clear-button">清空对话</button>
      </div>
    </div>

    <div class="chat-messages" ref="chatContainerRef">
      <div v-if="chatMessages.length === 0" class="empty-chat">
        <div class="empty-chat-content">
          <h3>开始与AI助手聊天</h3>
          <p>可以询问任何问题，AI助手会尽力帮助您</p>
        </div>
      </div>

      <div
          v-for="(message, index) in chatMessages"
          :key="index"
          :class="['message', message.role]"
      >
        <div class="message-avatar">
          <span v-if="message.role === 'user'">👤</span>
          <span v-else-if="message.role === 'assistant'">🤖</span>
          <span v-else>ℹ️</span>
        </div>
        <div class="message-content">
          <div
              :class="['message-text', { 'error-message': message.isError }]"
              v-if="message.role === 'user' || message.isError"
          >
            {{ message.content }}
            <span v-if="message.loading" class="loading-indicator">▋</span>
          </div>
          <!-- 使用v-html支持富文本显示AI回复 -->
          <div
              v-else
              :class="['message-text', 'markdown-content']"
              v-html="formatMarkdown(message.content)"
          >
          </div>
          <span v-if="message.loading" class="loading-indicator">▋</span>
        </div>
      </div>
    </div>

    <div class="chat-input-container">
      <textarea
          v-model="userInput"
          class="chat-input"
          placeholder="输入消息..."
          @keydown="handleKeyDown"
          :disabled="isLoading"
      ></textarea>
      <button
          @click="sendMessage"
          class="send-button"
          :disabled="isLoading || !userInput.trim()"
      >
        <span v-if="isLoading">发送中...</span>
        <span v-else>发送</span>
      </button>
    </div>

    <div class="chat-footer">
      <details class="settings-panel">
        <summary>高级设置</summary>
        <div class="settings-content">
          <div class="setting-item">
            <label>系统提示:</label>
            <input v-model="chatConfig.system_message" type="text" class="setting-input" />
          </div>
          <div class="setting-item">
            <label>温度 ({{ chatConfig.temperature }}):</label>
            <input
                v-model="chatConfig.temperature"
                type="range"
                min="0"
                max="1"
                step="0.1"
                class="setting-slider"
            />
          </div>
          <div class="setting-item">
            <label>最大 Token ({{ chatConfig.max_tokens }}):</label>
            <input
                v-model.number="chatConfig.max_tokens"
                type="number"
                min="100"
                max="8192"
                class="setting-input"
            />
          </div>
        </div>
      </details>
    </div>
  </div>
</template>

<style scoped>
.chat-container {
  display: flex;
  flex-direction: column;
  height: 100%;
  max-height: 100vh;
  background-color: #f5f7f9;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
}

.chat-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 20px;
  background-color: #ffffff;
  border-bottom: 1px solid #e0e0e0;
}

.chat-header h2 {
  margin: 0;
  color: #333;
  font-weight: 600;
  font-size: 1.25rem;
}

.chat-actions {
  display: flex;
  gap: 10px;
}

.model-selector {
  padding: 6px 10px;
  border-radius: 4px;
  border: 1px solid #ddd;
  background-color: #fff;
  font-size: 0.9rem;
}

.clear-button {
  padding: 6px 12px;
  background-color: #f3f4f6;
  border: 1px solid #ddd;
  border-radius: 4px;
  cursor: pointer;
  font-size: 0.9rem;
  transition: background-color 0.2s;
}

.clear-button:hover {
  background-color: #e2e4e7;
}

.chat-messages {
  flex-grow: 1;
  padding: 20px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.empty-chat {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  color: #666;
  text-align: center;
}

.empty-chat-content {
  max-width: 300px;
}

.empty-chat h3 {
  margin-bottom: 8px;
  font-weight: 600;
}

.message {
  display: flex;
  gap: 12px;
  max-width: 85%;
}

.message.user {
  align-self: flex-end;
  flex-direction: row-reverse;
}

.message.assistant {
  align-self: flex-start;
  margin-right: auto;
}

.message.system {
  align-self: center;
  color: #666;
  font-style: italic;
  max-width: 100%;
}

.message-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #e8e8e8;
  font-size: 1.2rem;
  flex-shrink: 0;
}

.user .message-avatar {
  background-color: #e3f1fd;
}

.assistant .message-avatar {
  background-color: #effcf0;
}

.message-content {
  background-color: #fff;
  padding: 12px 16px;
  border-radius: 12px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  line-height: 1.5;
}

.user .message-content {
  background-color: #1890ff;
  color: white;
  border-top-right-radius: 2px;
}

.assistant .message-content {
  background-color: #f2f3f5;
  border-top-left-radius: 2px;
  align-self: flex-start;
  text-align: left;
}

.message-text {
  white-space: pre-wrap;
  word-break: break-word;
}

/* Markdown内容样式 */
.markdown-content {
  width: 100%;
  font-size: 0.92rem;
  line-height: 1.2;
}

.markdown-content p {
  margin: 0;
  line-height: 1.2;
}

.markdown-content code {
  background-color: rgba(0,0,0,0.05);
  padding: 0.2em 0.4em;
  border-radius: 3px;
  font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
  font-size: 0.9em;
}

.markdown-content pre {
  background-color: #f6f8fa;
  border-radius: 4px;
  padding: 8px;
  overflow: auto;
  margin: 0;
  font-size: 0.85em;
}

.markdown-content pre code {
  background-color: transparent;
  padding: 0;
  white-space: pre;
  display: block;
  line-height: 1.3;
}

.markdown-content h1,
.markdown-content h2,
.markdown-content h3,
.markdown-content h4,
.markdown-content h5,
.markdown-content h6 {
  margin: 0;
  font-weight: 600;
  line-height: 1.15;
}

.markdown-content ul,
.markdown-content ol {
  padding-left: 1.5em;
  margin: 0;
}

.markdown-content li {
  margin: 0;
  line-height: 1.2;
}

.markdown-content blockquote {
  margin: 0;
  padding: 0 0.8em;
  color: #6a737d;
  border-left: 0.2em solid #dfe2e5;
  line-height: 1.2;
}

.markdown-content table {
  border-collapse: collapse;
  width: 100%;
  margin: 0;
  font-size: 0.9em;
}

.markdown-content table th,
.markdown-content table td {
  padding: 4px 8px;
  border: 1px solid #dfe2e5;
}

.markdown-content table tr {
  background-color: #fff;
  border-top: 1px solid #c6cbd1;
}

.markdown-content table tr:nth-child(2n) {
  background-color: #f6f8fa;
}

.loading-indicator {
  display: inline-block;
  animation: blink 1s infinite;
  font-weight: bold;
  margin-left: 4px;
}

.error-message {
  color: #ff4d4f;
}

@keyframes blink {
  0%, 100% { opacity: 0; }
  50% { opacity: 1; }
}

.chat-input-container {
  display: flex;
  padding: 16px;
  background-color: #fff;
  border-top: 1px solid #e0e0e0;
  gap: 10px;
}

.chat-input {
  flex-grow: 1;
  min-height: 40px;
  max-height: 120px;
  padding: 12px 16px;
  border: 1px solid #ddd;
  border-radius: 8px;
  resize: none;
  font-family: inherit;
  font-size: 0.95rem;
  line-height: 1.4;
  transition: border-color 0.2s;
}

.chat-input:focus {
  outline: none;
  border-color: #1890ff;
}

.send-button {
  padding: 0 20px;
  background-color: #1890ff;
  color: white;
  border: none;
  border-radius: 8px;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 0.2s;
  white-space: nowrap;
}

.send-button:hover {
  background-color: #40a9ff;
}

.send-button:disabled {
  background-color: #bfbfbf;
  cursor: not-allowed;
}

.chat-footer {
  padding: 0 16px 16px;
  background-color: #fff;
}

.settings-panel {
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  overflow: hidden;
}

.settings-panel summary {
  padding: 10px;
  cursor: pointer;
  user-select: none;
  background-color: #f9f9f9;
  font-weight: 500;
}

.settings-panel summary:hover {
  background-color: #f2f2f2;
}

.settings-content {
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.setting-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.setting-item label {
  font-size: 0.9rem;
  color: #555;
}

.setting-input {
  padding: 8px 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 0.9rem;
}

.setting-slider {
  width: 100%;
}
</style>